package environment
{
    import away3DExtensions.ColoredSubGeometry;
    
    import away3d.core.base.IRGBABufferRenderable;
    import away3d.core.base.SubGeometry;
    import away3d.materials.DefaultMaterialBase;
    import away3d.materials.MaterialBase;
    import away3d.materials.methods.BufferColorMethod;
    import away3d.primitives.Plane;
    import away3d.primitives.WireframePlane;
    
    import objects.BitmapPlane;
    
    /**
     * @private
     */
    public class EnvironmentPlane extends Plane
    {
        protected var env : Environment;
        protected var envLayer :EnvironmentLayer;
        protected var heightMapFunction :Function;
        
        public function EnvironmentPlane(material:DefaultMaterialBase, env : Environment, envLayer : EnvironmentLayer, heightMapFunction : Function)
        {
            super(material, env.width * Environment.SIZE_MULTIPLIER, env.height * Environment.SIZE_MULTIPLIER, env.width-1, env.height-1, true, ColoredSubGeometry);
            
            this.env = env;
            this.envLayer = envLayer;
            this.heightMapFunction = heightMapFunction;
            
            material.addMethod(new BufferColorMethod (false, false, false));
        }
        
        /**
         * @inheritDoc
         */
        override protected function buildGeometry(target : SubGeometry) : void
        {
            var vertices : Vector.<Number>;
            var colorVertices : Vector.<Number>;
            var normals : Vector.<Number>;
            var tangents : Vector.<Number>;
            var indices : Vector.<uint>;
            var x : Number, y : Number;
            var numInds : uint;
            var base : uint;
            var tw : uint = _segmentsW+1;
            var numVerts : uint = (_segmentsH + 1) * tw;
            
            if (numVerts == target.numVertices)
            {
                vertices = target.vertexData;
                colorVertices = (target as IRGBABufferRenderable).getRGBAVertices();
                normals = target.vertexNormalData;
                tangents = target.vertexTangentData;
                indices = target.indexData;
            }
            else
            {
                vertices = new Vector.<Number>(numVerts * 3, true);
                colorVertices = new Vector.<Number>(numVerts * 4, true);
                normals = new Vector.<Number>(numVerts * 3, true);
                tangents = new Vector.<Number>(numVerts * 3, true);
                indices = new Vector.<uint>(_segmentsH * _segmentsW * 6, true);
            }
            
            numVerts = 0;
            var numColors : int = 0;
            
            for (var yi : uint = 0; yi <= _segmentsH; ++yi)
            {
                for (var xi : uint = 0; xi <= _segmentsW; ++xi)
                {
                    var envVert : EnvVert = env.verts[xi][yi];
                    
                    x = (xi/_segmentsW)*_width;
                    y = (yi/_segmentsH)*_height;
                    
                    var pixel : uint = envLayer.bitmapData.getPixel32(xi, yi);
                    var value : uint = (pixel >> envLayer.bitmapBitshift) & 0xFF;
                    
                    envVert.vertIxs[envLayer.layerIx] = numVerts;
                    envVert.colorIxs[envLayer.layerIx] = numColors;
                    
                    var a : uint = (pixel >> 24) & 0xFF;
                    var r : uint = (pixel >> 16) & 0xFF; 
                    var g : uint = (pixel >> 8) & 0xFF; 
                    var b : uint = pixel & 0xFF;
                    
                    var bo : int = Environment.BORDER;
                    
                    if (xi < bo || yi < bo || yi > _segmentsH - bo || xi > _segmentsH - bo)
                    {
                        a = 0xFF;
                        r = g = b = 0x00;
                        pixel = 0xFF000000;
                    }
                    else if (Math.abs(yi - _segmentsH / 2) < Environment.NO_MANS_WIDTH)
                    {
                        a = 0x99;
                        g = 0x11;
                        r = 0x33;
                        b = 0xFF;
                        pixel = 0x993311FF;
                    }
                    
                    vertices[numVerts] = x;
                    
                    normals[numVerts] = 0;
                    tangents[numVerts++] = 1;
                    
                    colorVertices[numColors++] = (r as Number) / 256;
                    colorVertices[numColors++] = (g as Number) / 256;
                    colorVertices[numColors++] = (b as Number) / 256;
                    colorVertices[numColors++] = (a as Number) / 256;
                    
                    vertices[numVerts] = y;
                    normals[numVerts] = 0;
                    tangents[numVerts++] = 0;
                    
                    vertices[numVerts] = heightMapFunction != null ? heightMapFunction(x, y, pixel) : 1;
                    normals[numVerts] = -1;
                    tangents[numVerts++] = 0;
                    
                    if (xi != _segmentsW && yi != _segmentsH)
                    {
                        base = xi + yi*tw;
                        indices[numInds++] = base;
                        indices[numInds++] = base + tw;
                        indices[numInds++] = base + tw + 1;
                        indices[numInds++] = base;
                        indices[numInds++] = base + tw + 1;
                        indices[numInds++] = base + 1;
                    }
                }
            }
            
            target.updateVertexData(vertices);
            (target as IRGBABufferRenderable).updateRGBAVertices(colorVertices);
            target.updateVertexNormalData(normals);
            target.updateVertexTangentData(tangents);
            target.updateIndexData(indices);
        }
        
        public function getVertValue(vertIx : int) : Number
        {
            return _subGeometry.vertexData[vertIx];
        }
        
        public function getVertColor(colorIx : int) : Number
        {
            return (_subGeometry as IRGBABufferRenderable).getRGBAVertices()[colorIx];
        }
        
        public function setVertValue(vertIx : int, value : Number) : void
        {
            _subGeometry.vertexData[vertIx] = value;
        }
        
        public function addVertValue(vertIx : int, valueChange : Number) : void
        {
            _subGeometry.vertexData[vertIx] += valueChange * Environment.SIZE_MULTIPLIER;
        }
        
        public function setVertColor(vertIx : int, value : Number) : void
        {
            (_subGeometry as IRGBABufferRenderable).getRGBAVertices()[vertIx] = value;
        }
        
        public function addVertColor(vertIx : int, valueChange : Number) : void
        {
            (_subGeometry as IRGBABufferRenderable).getRGBAVertices()[vertIx] += valueChange;
        }
        
        public function invalidateVertexBuffer() : void
        {
            _subGeometry.updateVertexData(_subGeometry.vertexData);
        }
        
        public function invalidateColorBuffer() : void
        {
            _subGeometry.updateVertexData((_subGeometry as IRGBABufferRenderable).getRGBAVertices());
        }
    }
}